package com.lucenten.collect.gnss.handler;

import cn.quevo.common.lang.BooleanUtils;
import cn.quevo.common.lang.StringUtils;
import cn.quevo.common.utils.OsContext;
import cn.quevo.core.spring.util.PropertiesUtils;
import com.lucenten.collect.gnss.entity.GnssFile;
import com.lucenten.collect.gnss.entity.SatelliteStation;
import com.lucenten.collect.gnss.enums.GnssFormat;
import com.lucenten.collect.gnss.enums.GnssSource;
import com.lucenten.collect.gnss.handler.impl.BackupGnssHandler;
import com.lucenten.collect.gnss.handler.tools.GnssContext;
import com.lucenten.collect.gnss.service.ObsErvationService;
import com.lucenten.collect.gnss.service.SatelliteStationService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 抽象实现
 */
@Slf4j
@Data
public abstract class AbstractGnssHandler implements GnssHandler {

    protected final static PropertiesUtils prop = new PropertiesUtils("/conf/gnss");
    protected final static boolean isDev = BooleanUtils.isTrue(prop.getProperties("collect.dev")) ? true : false;
    protected final static String COLLECT_SSOURCE = prop.getProperties("collect.source");
    protected final static String COLLECT_ROOT = prop.getProperties("collect.root");
    protected final static String COLLECT_BACKUP = prop.getProperties("collect.backup");
    /* private final static String COLLECT_RINEX = prop.getString("collect.rinex");
     private final static String COLLECT_TECPTEC = prop.getString("collect.tecptec");*/
    protected final static String COLLECT_TMP = prop.getProperties("collect.tmp");
    protected final static String COLLECT_ERROR = prop.getProperties("collect.error");
    //    private final static String COLLECT_GNSS = prop.getString("collect.gnss");
    protected final static String N_TEQC_RUN = prop.getProperties("teqc.run");
    protected final static String N_RUNPKR00_RUN = prop.getProperties("runpkr00.run");
    protected final static String N_CRX2RNX_RUN = prop.getProperties("crx2rnx.run");

    protected final static String[] FILE_NAMES = new String[]{"n","g","c","o","nav","obs"};
    protected final static String[] SOURCE_SUBS = prop.getProperties("collect.source.subs","").split(",");

    private GnssHandler chainHandler;
    protected SatelliteStationService satelliteStationService;
    protected ObsErvationService obsErvationService;

    public AbstractGnssHandler(SatelliteStationService satelliteStationService, ObsErvationService obsErvationService) {
        this.satelliteStationService = satelliteStationService;
        this.obsErvationService = obsErvationService;
    }
    protected void before(GnssFile gnssFile) {
    }

    protected void after(boolean isSuccess, GnssFile gnssFile) {
    }

    @Override
    public Boolean process(GnssFile gnssFile) {
        System.out.println(this.getClass().getName()+"  START DATE: "+ LocalDateTime.ofInstant(Instant.now(), ZoneId.of("UTC")));
        this.before(gnssFile);
        boolean isSuccess = this.doProcess(gnssFile);
        this.after(isSuccess,gnssFile);
        if (chainHandler != null) {
            try {
                System.out.println(this.getClass().getName()+"  END DATE: "+ LocalDateTime.ofInstant(Instant.now(), ZoneId.of("UTC")));
                return chainHandler.process(gnssFile);
            }catch (Exception e){
                log.error(e.getMessage(),e);
                // 如果出现异常，直接跳过，归档
                if (chainHandler instanceof BackupGnssHandler) {
                    ((BackupGnssHandler) chainHandler).setChainHandler(null);
                    chainHandler.process(gnssFile);
                }
            }
        }
        System.out.println(this.getClass().getName()+"  END DATE: "+ LocalDateTime.ofInstant(Instant.now(), ZoneId.of("UTC")));
        return isSuccess;
    }

    /*@Override
    public GnssHandler getGnssHandler(){
        return this.gnssHandler;
    }*/
    protected abstract boolean doProcess(GnssFile gnssFile);

    /**
     * 获取站点名称
     *
     * @param fileName
     * @return
     */
    protected String getSetationName(String fileName) {
        return fileName.substring(0,4);
    }

    /**
     * 获取新的站点名称
     *
     * @param fileName
     * @param stationName
     * @return
     */
    protected String getNewStationName(String fileName, String stationName) {
        fileName = fileName.toLowerCase();
        return fileName.startsWith(stationName) ? fileName : stationName + fileName.substring(4);
    }

    /**
     * 获取原始数据存储目录
     *
     * @param gnssSource
     * @return
     */
    protected String getSourcePath(GnssSource gnssSource) {
        return Paths.get(prop.getProperties("collect.source."+gnssSource.getName())).normalize().toString();
    }

    /**
     * 获取文件存储根目录
     *
     * @param gnssFile
     * @return
     */
    protected String getGnssRoot(GnssFile gnssFile){
        return COLLECT_ROOT + '/' + gnssFile.getRealType()+"/"+gnssFile.getGnssType().getPath();
    }

    /**
     * 获取备份路径
     *
     * @param gnssFile
     * @return
     */
    protected String getBackupPath(GnssFile gnssFile) {
        return Paths.get(this.getGnssRoot(gnssFile),prop.getProperties("collect.backup"),gnssFile.getDayOfYearPath()).normalize().toString();
    }

    /**
     * 获取临时文件存储路径
     *
     * @param tempType
     * @return
     */
    protected String getTempPath(String tempType, GnssFile gnssFile) {
        return Paths.get(this.getGnssRoot(gnssFile), prop.getProperties("collect.tmp." + tempType), gnssFile.getDatePath(),gnssFile.getStationId()).normalize().toString();
    }

    /**
     * 获取错误文件存储路径
     *
     * @param gnssFile
     * @return
     */
    protected String getErrorPath(GnssFile gnssFile) {
        return Paths.get(COLLECT_ERROR,gnssFile.getRealType(), gnssFile.getGnssType().getPath(), gnssFile.getDatePath(),gnssFile.getStationId()).normalize().toString();
    }

    /**
     * 格式化后的数据存储目录
     *
     * @param format
     * @return
     */
    protected String getDataFormatPath(GnssFormat format, GnssFile gnssFile) {
        return Paths.get(this.getGnssRoot(gnssFile), prop.getProperties("collect.format."+format.getName()), gnssFile.getDayOfYearPath()).normalize().toString();
    }

    /**
     * 获取解压后的实际路径
     *
     * @param gnssFile
     * @param fileName
     * @return
     */
    protected Path getUnZipPath(GnssFile gnssFile, String fileName){
        String year = gnssFile.getYear().toString().substring(2);
        String parentPath = year.concat(fileName.substring(fileName.length()-1));
        return Paths.get(this.getDataFormatPath(GnssFormat.RINEX,gnssFile),parentPath,fileName);
    }

    protected String getReNewPath(String oPath, String ext) {
        return oPath.substring(oPath.lastIndexOf(".") - 1).concat(ext);
    }
    /**
     * 获取或替换站点名称
     *
     * @param stationName
     * @param gnssFile
     * @return
     */
    protected String getOrReplaceStation(String stationName, GnssFile gnssFile){
        if (StringUtils.isBlank(gnssFile.getStationName())) {
            gnssFile.setStationName(stationName);
            gnssFile.setReStationName(stationName);
        }
        final String key = gnssFile.getStationId() + "," + stationName;
        if (gnssFile.getStations().containsKey(key)) {
            gnssFile.setStation(gnssFile.getStations().get(key));
            stationName = gnssFile.getStation().getReStationName();
            gnssFile.setReStationName(stationName);
        }else {
            gnssFile.getStorageStations().put(key, SatelliteStation.getInstance(gnssFile.getStationId(), stationName));
        }
        return stationName;
    }

    /**
     * 获取实际可执行文件路径
     *
     * @param index
     * @return
     */
    protected String getTeqcRun(Integer index) {
        return getOrCreateRun(N_TEQC_RUN, index);
    }

    protected String getRunpkr00Run(Integer index) {
        return getOrCreateRun(N_RUNPKR00_RUN, index);
    }

    protected String getCrx2rnxRun(Integer index) {
        return getOrCreateRun(N_CRX2RNX_RUN, index);
    }

    private String getOrCreateRun(String path,Integer index) {
        int lastIndex = path.lastIndexOf(".");
        String exe = "";
        if (lastIndex <= 0) {
            exe = path.concat(index.toString());
        }else {
            exe = path.substring(0,lastIndex).concat("_"+index.toString()).concat(path.substring(lastIndex));
        }
        if (Files.exists(Paths.get(exe))) {
            return exe;
        }

        try{
            Files.copy(Paths.get(path), Paths.get(exe));
        } catch (IOException e) {
            log.error("可执行程序复制失败", e);
        }
        return exe;
    }
}
